package com.demo.config.filter;

import com.alibaba.fastjson2.JSONObject;
import com.demo.common.constant.JWTConstants;
import com.demo.common.model.BusinsesEnum;
import com.demo.common.model.R;
import com.demo.common.model.SecurityUser;
import com.demo.common.utils.JWTUtils;
import com.demo.common.utils.ResponseUtils;

import com.demo.common.utils.TokenManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;


import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Set;

/*
    令牌 token转换过滤器
 */
@Component
@Slf4j
public class TokenFilter extends OncePerRequestFilter {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private TokenManager tokenManager;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 从请求头中获取 authorization 的值
        String authorizationValue = request.getHeader(JWTConstants.AUTHORIZATION);
        // 判断是否有值
        if (!StringUtils.hasText(authorizationValue)) {
            ResponseUtils.writeJson(response, R.FAIL(BusinsesEnum.TOKEN_INVALIDATE));
            return;
        }
        // 判断 authorization 值的格式是否正确
        if (!authorizationValue.startsWith(JWTConstants.BEARER)) {
            ResponseUtils.writeJson(response, R.FAIL(BusinsesEnum.TOKEN_INVALIDATE));
            return;
        }
        // 判断令牌 token 是否有值
        String jwt_token = authorizationValue.replaceFirst(JWTConstants.BEARER, "");
        // 判断令牌 token 是否有值
        if (!StringUtils.hasText(jwt_token)) {
            ResponseUtils.writeJson(response, R.FAIL(BusinsesEnum.TOKEN_EMPTY));
            return;
        }
        // 判断 令牌是否有效
        if (!JWTUtils.verifyJWT(jwt_token)) {
            ResponseUtils.writeJson(response, R.FAIL(BusinsesEnum.TOKEN_INVALIDATE));
            return;
        }
        // 判断令牌是否在redis中存储  判断令牌是否过期
        if (!redisTemplate.hasKey(JWTConstants.JWT_REDIS_KEY_PREFIX + jwt_token)) {
            ResponseUtils.writeJson(response, R.FAIL(BusinsesEnum.TOKEN_INVALIDATE));
            return;
        }

        // 获取记住我 标识 [从请求头中拿]
        Boolean rememberMe = Boolean.parseBoolean(request.getHeader("RememberMe"));

        // 刷新令牌 token 的失效时间
        tokenManager.flushTokenTime(jwt_token,rememberMe);

        // 解析 jwt 令牌, 获取用户认证信息 json 格式字符串
        String securityUserStr = JWTUtils.parseJWT(jwt_token);
        // 将 json格式字符串转换为安全认证用户对象
        SecurityUser securityUser = JSONObject.parseObject(securityUserStr, SecurityUser.class);
//        // 获取操作权限集合   [set转list]
//        Set<String> permissionList = securityUser.getPermissionLIst();
//        List<SimpleGrantedAuthority> list = permissionList.stream().map(SimpleGrantedAuthority::new).toList();
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(securityUser, null, AuthorityUtils.NO_AUTHORITIES);
        // 将当前请求的认证标签放到 security 容器中
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        // 放行
        filterChain.doFilter(request, response);
    }
}
